import fs from "fs";
import path from "path";
import { camelize } from "@vue/shared";
import glob from "fast-glob";
import { docRoot } from "../../../internal/build-utils/src";
import type { Plugin } from "vite";

type Append = Record<"headers" | "footers" | "scriptSetups", string[]>;

let compPaths: string[];

export function MarkdownTransform(): Plugin {
  return {
    name: "antd-xv-md-transform",

    enforce: "pre",

    async buildStart() {
      const pattern = `/component`;

      compPaths = await glob(pattern, {
        cwd: docRoot,
        absolute: true,
        onlyDirectories: true,
      });
    },

    async transform(code, id) {
      if (!id.endsWith(".md")) return;
      if (!id.includes("/component")) return;

      const componentId = path.basename(id, ".md");
      const append: Append = {
        headers: [],
        footers: [],
        scriptSetups: getExampleImports(componentId),
      };

      code = transformVpScriptSetup(code, append);

      if (compPaths.some((compPath) => id.startsWith(compPath))) {
        code = transformComponentMarkdown(id, componentId, code, append);
      }

      return combineMarkdown(code, [combineScriptSetup(append.scriptSetups), ...append.headers], append.footers);
    },
  };
}

const combineScriptSetup = (codes: string[]) =>
  `\n<script setup>
${codes.join("\n")}
</script>
`;

const combineMarkdown = (code: string, headers: string[], footers: string[]) => {
  const frontmatterEnds = code.indexOf("---\n\n");
  const firstHeader = code.search(/\n#{1,6}\s.+/);
  const sliceIndex = firstHeader < 0 ? (frontmatterEnds < 0 ? 0 : frontmatterEnds + 4) : firstHeader;

  if (headers.length > 0) code = code.slice(0, sliceIndex) + headers.join("\n") + code.slice(sliceIndex);
  code += footers.join("\n");

  return `${code}\n`;
};

const vpScriptSetupRE = /<vp-script\s(.*\s)?setup(\s.*)?>([\s\S]*)<\/vp-script>/;

const transformVpScriptSetup = (code: string, append: Append) => {
  const matches = code.match(vpScriptSetupRE);
  if (matches) code = code.replace(matches[0], "");
  const scriptSetup = matches?.[3] ?? "";
  if (scriptSetup) append.scriptSetups.push(scriptSetup);
  return code;
};

const transformComponentMarkdown = (id: string, componentId: string, code: string, append: Append) => {
  return code;
};

const getExampleImports = (componentId: string) => {
  const examplePath = path.resolve(docRoot, "examples", componentId);
  if (!fs.existsSync(examplePath)) return [];
  const files = fs.readdirSync(examplePath);
  const imports: string[] = [];

  for (const item of files) {
    if (!/\.vue$/.test(item)) continue;
    const file = item.replace(/\.vue$/, "");
    const name = camelize(`Ax-${componentId}-${file}`);

    imports.push(`import ${name} from '../examples/${componentId}/${file}.vue'`);
  }

  return imports;
};
